<template>
  <div class="mainForm">
    <el-form
      ref="mainform"
      :model="form.deliver"
      :rules="form.rules"
      label-width="80px"
      :class="`el-form__${layout}`"
    >
      <!-- prop属性用作绑定表单项的deliver数据key值，同时指定rules的校验规则列表的key值 -->
      <el-form-item
        :class="{ label_align_left: label_align_left }"
        v-for="(protoItem, index) in form.proto"
        :key="index"
        :label="protoItem.label"
        :prop="protoItem.value"
        :style="protoItem.prepend_style"
      >
        <el-col :span="18">
          <!-- element ui text类型的input框 -->
          <el-input
            v-if="protoItem.type === 'text'"
            type="text"
            v-model="form.deliver[protoItem.value]"
            :size="protoItem.size"
            :placeholder="protoItem.placeholder"
            :disabled="protoItem.disabled"
            :readonly="protoItem.readonly"
            :minlength="protoItem.minlength"
            :maxlength="protoItem.maxlength"
            :prefix-icon="protoItem.prefix_icon"
            :suffix-icon="protoItem.suffix_icon"
            :clearable="protoItem.clearable"
            :show-password="protoItem.show_password"
            :validate-event="protoItem.validate_event"
            @change="inputChange($event, '@change')"
          >
            <template slot="prepend" v-if="protoItem.prepend_icon">
              <i :class="protoItem.prepend_icon" class="prepend_icon"></i>
            </template>
          </el-input>

          <!-- element ui textarea类型的input框 -->
          <el-input
            v-if="protoItem.type === 'textarea'"
            type="textarea"
            v-model="form.deliver[protoItem.value]"
            :size="protoItem.size"
            :placeholder="protoItem.placeholder"
            :disabled="protoItem.disabled"
            :readonly="protoItem.readonly"
            :minlength="protoItem.minlengths"
            :maxlength="protoItem.maxlength"
            :autosize="protoItem.autosize"
            :clearable="protoItem.clearable"
            :validate-event="protoItem.validate_event"
            show-word-limit
            @change="textareaChange($event, '@change')"
          ></el-input>

          <!-- element ui 常规select选择器 -->
          <el-select
            v-if="protoItem.type === 'select'"
            v-model="form.deliver[protoItem.value]"
            :disabled="protoItem.disabled"
            :clearable="protoItem.clearable"
            :filterable="protoItem.filterable"
            :placeholder="protoItem.placeholder"
            :multiple="protoItem.multiple"
            :collapse-tags="protoItem.collapse_tags"
            :multiple-limit="protoItem.multiple_limit"
            :validate-event="protoItem.validate_event"
            @change="selectChange($event, '@change')"
          >
            <el-option
              v-for="item in protoItem.options"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            >
            </el-option>
          </el-select>

          <!-- element ui group类型的select选择器 -->
          <el-select
            v-if="protoItem.type === 'select_group'"
            v-model="form.deliver[protoItem.value]"
            :disabled="protoItem.disabled"
            :clearable="protoItem.clearable"
            :placeholder="protoItem.placeholder"
            :multiple="protoItem.multiple"
            :collapse-tags="protoItem.collapse_tags"
            :multiple-limit="protoItem.multiple_limit"
            :validate-event="protoItem.validate_event"
            @change="selectChange($event, '@change')"
          >
            <el-option-group
              v-for="group in protoItem.options"
              :key="group.label"
              :label="group.label"
            >
              <el-option
                v-for="item in group.options"
                :key="item.value"
                :label="item.label"
                :value="item.value"
              >
              </el-option>
            </el-option-group>
          </el-select>

          <!-- element ui cascader级联选择器 -->
          <el-cascader
            v-if="protoItem.type === 'cascader'"
            v-model="form.deliver[protoItem.value]"
            :clearable="protoItem.clearable"
            :disabled="protoItem.disabled"
            :validate-event="protoItem.validate_event"
            :show-all-levels="protoItem.show_all_levels"
            :separator="protoItem.separator"
            :size="protoItem.size"
            :options="protoItem.options"
            :props="{ expandTrigger: 'hover' }"
            @change="cascaderChange($event, '@change')"
          ></el-cascader>

          <!-- element ui datePicker日期选择器 -->
          <el-date-picker
            v-if="protoItem.type === 'datePicker'"
            v-model="form.deliver[protoItem.value]"
            :type="protoItem.subType"
            :disabled="protoItem.disabled"
            :readonly="protoItem.readonly"
            :clearable="protoItem.clearable"
            :prefix-icon="protoItem.prefic_icon"
            :clear-icon="protoItem.clear_icon"
            :picker-options="protoItem.pickerOptions"
            :unlink-panels="protoItem.unlink_panels"
            :validate-event="protoItem.validate_event"
            :start-placeholder="protoItem.start_placeholder"
            :end-placeholder="protoItem.end_placeholder"
            :range-separator="protoItem.range_separator"
            :placeholder="protoItem.placeholder"
            :format="protoItem.format"
            :value-format="protoItem.value_format"
            :align="protoItem.align"
            :size="protoItem.size"
            @change="dataPickerChange($event, '@change')"
          >
          </el-date-picker>

          <!-- element ui input number数值计步器-->
          <el-input-number
            v-if="protoItem.type === 'inputNumber'"
            v-model="form.deliver[protoItem.value]"
            :min="protoItem.min"
            :max="protoItem.max"
            :step="protoItem.step"
            :step-strictly="protoItem.step_strictly"
            :precision="protoItem.precision"
            :size="protoItem.size"
            :disabled="protoItem.disabled"
            :controls="protoItem.controls"
            :controls-position="protoItem.controls_position"
            :label="protoItem.label"
            :placeholder="protoItem.placeholder"
            @change="numberChange($event, '@change')"
          ></el-input-number>
        </el-col>
      </el-form-item>
      <el-form-item
        v-if="showSelfLine"
        :class="{ label_align_left: label_align_left }"
        :label="selfLabel"
        :style="''"
      ></el-form-item>
      <div class="selfline" v-if="showSelfLine">
        <slot></slot>
      </div>
    </el-form>
  </div>
</template>

<script>
export default {
  name: "ocn-mainForm",
  props: {
    // column-垂直分布 row-水平分布
    layout: {
      type: String,
      default: "column",
    },

    label_align_left: {
      type: Boolean,
      default: false,
    },

    form: {
      type: Object,
      default: () => {
        return {
          // 绑定表单v-module 数据的属性值，最终提交表单所提交的是 deliver对象
          deliver: {
            protoItem_value: "", // protoItem_value 指代proto每一个配置的value属性
          },
          rules: {
            // protoItem_value  指的是，表单提交对象deliver里的 key 值，根据key值对应相应的规则对象
            protoItem_value: [
              {
                required: true, // 是否必填
                message: "请输入内容", // 未必填提示的异常信息
                trigger: "change", // 校验时机 blur-输入项失去焦点时；change-输入项内容变更时；
              },
              {
                min: 3, // 最小输入字符长度
                max: 5, // 最大输入字符长度
                message: "长度在 3 到 5 个字符", // 未符合规则时提示的异常信息
                trigger: "change", // 校验时机 blur-输入项失去焦点时；change-输入项内容变更时；
              },
              {
                validator: (rule, value, callback) => {},
                trigger: "change",
              },
            ],
          },
          // 条件渲染表单项UI的属性配置对象
          proto: [
            {
              // 配置示例
              type: "",
              label: "",
              value: "",
              placeholder: "",
              size: "medium",

              clearable: false,
              disabled: false,
              validate_event: true,
            },
          ],
        };
      },
    },

    showSelfLine: {
      type: Boolean,
      default: false,
    },

    selfLabel: {
      type: String,
      default: '',
    }
  },
  data() {
    return {
      busMsg: {
        formItem: "",
        itemValue: "",
        eventType: "",
        msg: "",
      },
    };
  },
  created() {},
  mounted() {},
  activated() {},
  deactivated() {},
  methods: {
    /**
     * @author QL
     * @functionName update
     * @param { Object } formConfig
     * @date 2022-01-10 17:14:49
     * @version V..
     * @description 手动ref引用触发传入表单配置对象更新表单配置
     */
    update(formConfig) {
      this.$set("form", formConfig);
    },

    /**
     * @author QL
     * @functionName resetForm
     * @date 2022-01-14 15:18:12
     * @version V..
     * @description 供父级组件调用重置表单数据，消除规则校验提示的异常状态
     */
    resetForm() {
      this.$refs.mainform.resetFields();
    },

    /**
     * @author QL
     * @functionName onSubmit
     * @date 2022-01-10 17:05:15
     * @version V..
     * @description 提交表单触发方法
     */
    onSubmit() {
      this.$refs.mainform.validate((valid) => {
        if (valid) {
          this.$emit("submit", { ...this.form.deliver });
        } else {
          console.log("error submit!!");
          return false;
        }
      });
    },

    /**
     * @author QL
     * @functionName getValue
     * @date 2022-01-10 17:04:32
     * @version V..
     * @description 获取表单的提交对象
     */
    getValue() {
      return { ...this.form.deliver };
    },

    /**
     * @author QL
     * @functionName inputChange
     * @param { Object } val
     * @param { String } eventType
     * @date 2022-01-10 17:03:08
     * @version V..
     * @description input组件的change方法绑定handle方法
     */
    inputChange(val, eventType) {
      this.$set(this, "busMsg", {
        formItem: "input",
        itemValue: val,
        eventType: eventType,
        msg: `input值变化为：${val}`,
      });
      this.formEventBus();
    },

    /**
     * @author QL
     * @functionName textareaChange
     * @param { Object } val
     * @param { String } eventType
     * @date 2022-01-10 17:03:08
     * @version V..
     * @description input的textarea组件的change方法绑定handle方法
     */
    textareaChange(val, eventType) {
      this.$set(this, "busMsg", {
        formItem: "textarea",
        itemValue: val,
        eventType: eventType,
        msg: `textarea值变化为：${val}`,
      });
      this.formEventBus();
    },

    /**
     * @author QL
     * @functionName selectChange
     * @param { Object } val
     * @param { String } eventType
     * @date 2022-01-10 17:03:08
     * @version V..
     * @description select组件的change方法绑定handle方法
     */
    selectChange(val, eventType) {
      this.$set(this, "busMsg", {
        formItem: "select",
        itemValue: val,
        eventType: eventType,
        msg: `select值变化为：${val}`,
      });
      this.formEventBus();
    },

    /**
     * @author QL
     * @functionName cascaderChange
     * @param { Object } val
     * @param { String } eventType
     * @date 2022-01-10 17:03:08
     * @version V..
     * @description cascader组件的change方法绑定handle方法
     */
    cascaderChange(val, eventType) {
      this.$set(this, "busMsg", {
        formItem: "cascader",
        itemValue: val,
        eventType: eventType,
        msg: `cascader值变化为：${val}`,
      });
      this.formEventBus();
    },

    /**
     * @author QL
     * @functionName dataPickerChange
     * @param { Object } val
     * @param { String } eventType
     * @date 2022-01-10 17:03:08
     * @version V..
     * @description dataPicker组件的change方法绑定handle方法
     */
    dataPickerChange(val, eventType) {
      this.$set(this, "busMsg", {
        formItem: "dataPicker",
        itemValue: val,
        eventType: eventType,
        msg: `dataPicker值变化为：${val}`,
      });
      this.formEventBus();
    },

    /**
     * @author QL
     * @functionName numberChange
     * @param { Object } val
     * @param { String } eventType
     * @date 2022-01-10 17:03:08
     * @version V..
     * @description inputNumber组件的change方法绑定handle方法
     */
    numberChange(val, eventType) {
      this.$set(this, "busMsg", {
        formItem: "inputNumber",
        itemValue: val,
        eventType: eventType,
        msg: `inputNumber值变化为：${val}`,
      });
      this.formEventBus();
    },

    /**
     * @author QL
     * @functionName formEventBus
     * @date 2022-01-10 17:02:09
     * @version V..
     * @description 事件总线方法，用于表单项的操作方法统一处理暴露给父组件
     */
    formEventBus() {
      this.$emit("formEventBus", this.busMsg);
      this.$set(this, "busMsg", {
        formItem: "",
        itemValue: "",
        eventType: "",
        msg: "",
      });
    },
  },
};
</script>
<style lang="scss" scoped>
.mainForm {
  width: 100%;
  height: 100%;
  /* stretch 属性标识按照对称轴垂直方向沾满容器 前提是容器没有设置对称轴垂直方向的距离属性 width/height*/
  align-self: stretch;
  // display: flex;
  // flex-direction: column;
  // justify-content: center;
  // align-items: center;
}

.el-form__column {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  align-items: flex-start;
  align-self: stretch;
  .el-form-item {
    align-self: stretch;
  }

  .selfline {
    align-self: stretch;
  }
}

.el-form__row {
  width: 100%;
  // height: 100%;
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: flex-start;
  align-items: flex-start;
  align-self: stretch;
  flex: 0 0 auto; // 禁止放大和缩小
  .el-form-item {
    width: 48%;
    margin: 10px;
    flex: 0 0 auto; // 禁止放大和缩小
  }

  .selfline {
    width: 98%;
    margin: 10px;
    flex: 0 0 auto; // 禁止放大和缩小
  }
}

/deep/ .label_align_left .el-form-item__label {
  text-align: left !important;
}

/deep/ .el-input-group__prepend {
  background-color: var(--background_color) !important;
  color: var(--color) !important;
}

/deep/ .el-textarea textarea {
  padding-bottom: 13px;
}
/deep/ .el-textarea .el-input__count {
  height: 12px;
  line-height: 12px;
}
</style>
